﻿#region License statement
// NJamb, a specification and delta-specification DSL
// Copyright (c) 2010-2011, Mark Knell
// Published under the MIT License; all other rights reserved
#endregion

#region using...
using System;
using System.Linq.Expressions;
using Stile.Types.Expressions;
#endregion

namespace NJamb.Parser.SubjectBuilders
{
	public class SubjectBuilder<THost> : ISubjectBuilder<THost>,
		ICollaboratingSubjectBuilder<THost>
		where THost : class
	{
		public SubjectBuilder(Expression<Func<THost>> hostExpression)
		{
			Expression = hostExpression;
			LazyHostDescription = Expression.Body.ToLazyDebugString();
		}

		public Expression<Func<THost>> Expression { get; private set; }
		public Lazy<string> LazyHostDescription { get; private set; }

		public ICollaboratingSubjectBuilder<THost> Xray
		{
			get { return this; }
		}

		public string Describe<TSubject>(Expression<Func<THost, TSubject>> refinement)
		{
			return Describe((LambdaExpression) refinement);
		}

		public Lazy<string> Describe(Expression<Action<THost>> refinement)
		{
			return new Lazy<string>(() => Describe((LambdaExpression) refinement));
		}

		private string Describe(LambdaExpression refinement)
		{
			string hostDescription = LazyHostDescription.Value;
			if (refinement.Parameters.Count == 1)
			{
				string bodySubstring = ExpressionExtensions.GetBodySubstring(refinement);
				if (!string.IsNullOrWhiteSpace(bodySubstring))
				{
					return string.Join(".", hostDescription, bodySubstring);
				}
				return hostDescription;
			}
			string refinementDescription = refinement.ToDebugString();
			return string.Format("{0} transformed by {1}", hostDescription, refinementDescription);
		}
	}
}
